// 导入axios实例
import axios from 'axios';
// 导入一些常量
import {LESSON_SERVER_HOST, TOKEN_EXPIRING_SOON} from '@/constant';

/* =============== Axios实例配置 =============== */

// 创建Axios实例 `LESSON_SERVER_AXIOS`: 配置请求前缀和超时时间
export const LESSON_SERVER_AXIOS = axios.create({
    baseURL: `${LESSON_SERVER_HOST}/api/v1`, timeout: 5000
});
// LESSON_SERVER_AXIOS请求拦截器: 在发送请求前执行
LESSON_SERVER_AXIOS.interceptors.request.use(
    // 正常时执行该函数，req为当前请求对象
    req => {
        // 统一打印请求数据，便于测试，生产时删除
        console.log('拦截到请求: ', req);
        // 从sessionStorage中获取Token令牌
        let token = sessionStorage.getItem("token");
        // 若Token令牌存在，则将Token令牌存入请求头
        if (token) req.headers['token'] = token;
        // 无论Token是否获取成功，都放行请求
        return req;
    },
    // 异常时执行该函数，e为异常对象: 异常时阻止该响应并展示异常信息
    e => Promise.reject(e)
);

// LESSON_SERVER_AXIOS响应拦截器: 在接收到响应之后执行
LESSON_SERVER_AXIOS.interceptors.response.use(
    // 正常时执行该函数，req为当前请求对象
    resp => {
        // 统一打印响应数据，便于测试，生产时删除
        console.log('拦截到响应: ', resp);
        // 请求: 查询轮播图
        // 1. 进入axios的请求拦截器，拼装了token
        // 2. 进入服务端拦截器，发现token即将过期
        // 3. 服务端直接返回一个1004 和 新的token
        // 4. 进入axios的响应拦截器，判断响应码是否为 1004
        // 5. 从响应中获取 新的Token 令牌
        // 6. 更新sessionStorage中的token
        // 7. 重新发送请求: 查询轮播图
        // 8. 进入axios的请求拦截器，拼装了token
        // 判断需要对Token进行续期: 约定Token即将过期时后台会返回一个 `code=1004` 的响应
        if (resp.data.code === TOKEN_EXPIRING_SOON) {
            console.log(" >> Token自动续期-开始，原Token: {}", sessionStorage.getItem("token"));
            // 从响应中获取新的Token令牌
            let newToken = resp.data.data;
            // 更新sessionStorage中的Token令牌
            sessionStorage.setItem("token", newToken);
            // 将新的Token令牌设置到请求头
            LESSON_SERVER_AXIOS.defaults.headers['token'] = newToken;
            console.log(" >> Token自动续期-结束，新Token: {}", newToken);
            // 携带新Token重新发送请求
            return LESSON_SERVER_AXIOS.request(resp.config);
        }
        // 若不需要Token续期，则直接放行请求
        return resp;
    },
    // 异常时执行该函数，e为异常对象: 异常时阻止该响应并展示异常信息
    err => Promise.reject(err)
);